package com.only4play.session.local;

import com.only4play.auth.ExpirationPolicy;
import com.only4play.auth.RefreshTokenContent;
import com.only4play.session.RefreshTokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author liyuncong
 * @version 1.0
 * @file LocalRefreshTokenManager
 * @brief 本地刷新令牌管理
 * @details 本地刷新令牌管理
 * @date 2023-11-18
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2023-11-18               liyuncong          Created
 */
@Slf4j
@Component
public class LocalRefreshTokenManager implements RefreshTokenManager, ExpirationPolicy {

//    @Value("${sso.timeout}")
    private int timeout = 600;

    private Map<String, DummyRefreshToken> refreshTokenMap = new ConcurrentHashMap<>();

    @Override
    public void create(String refreshToken, RefreshTokenContent refreshTokenContent) {
        long expired = Instant.now().plusSeconds(getExpiresIn()).toEpochMilli();
        refreshTokenMap.put(refreshToken, new DummyRefreshToken(refreshTokenContent, expired));
    }

    @Override
    public RefreshTokenContent validate(String refreshToken) {
        DummyRefreshToken dummyRefreshToken = refreshTokenMap.remove(refreshToken);
        if (Objects.isNull(dummyRefreshToken) || Instant.now().isAfter(Instant.ofEpochMilli(dummyRefreshToken.expired))) {
            return null;
        }
        return dummyRefreshToken.refreshTokenContent;
    }


    @Override
    public int getExpiresIn() {
        return timeout;
    }

    @Scheduled(cron = SCHEDULED_CORN)
    @Override
    public void verifyExpired() {
        refreshTokenMap.forEach((refreshToken, dummyRefreshToken) -> {
            if (Instant.now().isAfter(Instant.ofEpochMilli(dummyRefreshToken.expired))) {
                refreshTokenMap.remove(refreshToken);
                log.info("refreshToken expired, refreshToken: {}", refreshToken);
            }
        });
    }

    private record DummyRefreshToken(RefreshTokenContent refreshTokenContent, long expired) {
    }

}
